// Copyright 2011 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * A class representing a map whose keys are strings. This is useful as an
 * alternative to a native JS object where the keys are arbitrary -- for
 * example, where the user may pass in the string 'hasOwnProperty' to be stored
 * as a key.
 *
 * @constructor
 */
flame.internal.StringMap = function() {
  /**
   * An object used as the underlying map.
   *
   * @type {!Object}
   */
  this.object_ = {};
};

/**
 * Insert a (key, value) pair into the map, replacing any previous pair for the
 * supplied key.
 *
 * @param {string} key
 * @param {*} value
 */
flame.internal.StringMap.prototype.insert = function(key, value) {
  if (typeof(key) != 'string') {
    throw new TypeError('Argument must be a string.');
  }

  this.object_[key] = value;
};

/**
 * Test whether the map contains the given key.
 *
 * @param {string} key
 * @return {boolean}
 */
flame.internal.StringMap.prototype.contains = function(key) {
  if (typeof(key) != 'string') {
    throw new TypeError('Argument must be a string.');
  }

  // Use hasOwnProperty.call because the user may have inserted the string
  // 'hasOwnProperty' into the set.
  return Object.hasOwnProperty.call(this.object_, key);
};

/**
 * Get the value associated with the supplied key. Throws an error for unknown
 * keys.
 *
 * @param {string} key
 * @return {*}
 */
flame.internal.StringMap.prototype.get = function(key) {
  if (typeof(key) != 'string') {
    throw new TypeError('Argument must be a string.');
  }

  if (!this.contains(key)) {
    throw new Error('Unknown key: ' + key);
  }

  return this.object_[key];
};

/**
 * Get a list of all keys in the map. The order is undefined.
 *
 * @return {!Array.<string>}
 */
flame.internal.StringMap.prototype.getKeys = function() {
  return /** @type{!Array.<string>} */(Object.keys(this.object_));
};
